package run.halo.app.service;

import java.util.Collection;
import java.util.List;
import java.util.Set;
import javax.validation.constraints.NotNull;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.lang.NonNull;
import org.springframework.transaction.annotation.Transactional;
import run.halo.app.model.entity.Site;
import run.halo.app.model.enums.SiteStatus;
import run.halo.app.model.params.SiteQuery;
import run.halo.app.model.vo.SiteDetailVO;
import run.halo.app.service.base.CrudService;

/**
 * Site service interface.
 *
 * @author johnniang
 * @author ryanwang
 * @author guqing
 * @date 2019 -03-14
 */
public interface SiteService extends CrudService<Site, Integer> {

    /**
     * Pages sites.
     *
     * @param siteQuery site query must not be null
     * @param pageable page info must not be null
     * @return a page of site
     */
    @NonNull
    Page<Site> pageBy(@NonNull SiteQuery siteQuery, @NonNull Pageable pageable);

    /**
     * Pages site by keyword
     *
     * @param keyword keyword
     * @param pageable pageable
     * @return a page of site
     */
    @NonNull
    Page<Site> pageBy(@NonNull String keyword, @NonNull Pageable pageable);

    /**
     * Page latest page.
     *
     * @param top the top
     * @return the page
     */
    Page<Site> pageLatest(int top);

    /**
     * Creates site by site param.
     *
     * @param site site must not be null
     * @param tagIds tag id set
     * @param categoryIds category id set
     * @param autoSave autoSave
     * @return site created
     */
    @NonNull
    SiteDetailVO createBy(@NonNull Site site, Set<Integer> tagIds, Set<Integer> categoryIds,
        boolean autoSave);

    /**
     * Updates site by site, tag id set and category id set.
     *
     * @param siteToUpdate site to update must not be null
     * @param tagIds tag id set
     * @param categoryIds category id set
     * @param autoSave autoSave
     * @return updated site
     */
    @NonNull
    SiteDetailVO updateBy(@NonNull Site siteToUpdate, Set<Integer> tagIds, Set<Integer> categoryIds,
        boolean autoSave);

    /**
     * Update status site.
     *
     * @param status the status
     * @param siteId the site id
     * @return the site
     */
    @Transactional(rollbackFor = Exception.class)
    Site updateStatus(SiteStatus status, Integer siteId);

    /**
     * Gets site by site status and slug.
     *
     * @param status site status must not be null
     * @param slug site slug must not be blank
     * @return site info
     */
    @NonNull
    Site getBy(@NonNull SiteStatus status, @NonNull String slug);

    /**
     * Gets site by site year and month and slug.
     *
     * @param year site create year.
     * @param month site create month.
     * @param slug site slug.
     * @return site info
     */
    @NonNull
    Site getBy(@NonNull Integer year, @NonNull Integer month, @NonNull String slug);

    /**
     * Gets site by site year and slug.
     *
     * @param year site create year.
     * @param slug site slug.
     * @return site info
     */
    @NonNull
    Site getBy(@NonNull Integer year, @NonNull String slug);

    /**
     * Gets site by site year and month and slug.
     *
     * @param year site create year.
     * @param month site create month.
     * @param slug site slug.
     * @param status site status.
     * @return site info
     */
    @NonNull
    Site getBy(@NonNull Integer year, @NonNull Integer month, @NonNull String slug,
        @NonNull SiteStatus status);

    /**
     * Gets site by site year and month and slug.
     *
     * @param year site create year.
     * @param month site create month.
     * @param day site create day.
     * @param slug site slug.
     * @return site info
     */
    @NonNull
    Site getBy(@NonNull Integer year, @NonNull Integer month, @NonNull Integer day,
        @NonNull String slug);

    /**
     * Gets site by site year and month and slug.
     *
     * @param year site create year.
     * @param month site create month.
     * @param day site create day.
     * @param slug site slug.
     * @param status site status.
     * @return site info
     */
    @NonNull
    Site getBy(@NonNull Integer year, @NonNull Integer month, @NonNull Integer day,
        @NonNull String slug, @NonNull SiteStatus status);

    /**
     * Removes sites in batch.
     *
     * @param ids ids must not be null.
     * @return a list of deleted site.
     */
    @NonNull
    List<Site> removeByIds(@NonNull Collection<Integer> ids);

    /**
     * Gets by slug.
     *
     * @param slug the slug
     * @return the by slug
     */
    Site getBySlug(String slug);

    /**
     * Publish a site visit event.
     *
     * @param siteId siteId must not be null
     */
    void publishVisitEvent(@NonNull Integer siteId);

    /**
     * Increase visit.
     *
     * @param visits the visits
     * @param siteId the site id
     */
    @Transactional
    void increaseVisit(long visits, Integer siteId);

    /**
     * Increase visit.
     *
     * @param siteId the site id
     */
    @Transactional(rollbackFor = Exception.class)
    void increaseVisit(Integer siteId);

    /**
     * Increase like.
     *
     * @param likes the likes
     * @param siteId the site id
     */
    @Transactional(rollbackFor = Exception.class)
    void increaseLike(long likes, Integer siteId);

    /**
     * Increase like.
     *
     * @param siteId the site id
     */
    @Transactional(rollbackFor = Exception.class)
    void increaseLike(Integer siteId);

    /**
     * Update status by ids list.
     *
     * @param ids the ids
     * @param status the status
     * @return the list
     */
    @Transactional(rollbackFor = Exception.class)
    List<Site> updateStatusByIds(List<Integer> ids, SiteStatus status);
}
